﻿using ASmile.ORM.BuildSQLText;
using ASmile.ORM.Entitys;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace ASmile.ORM.Cores
{
    public class DBContextDebug : DBContext
    {
        public DBContextDebug(EmDbType dbType, string connStr)
           : base(dbType, connStr)
        { }

        public DBContextDebug(string dbType, string connStr)
            : base(GetDbType(dbType), connStr)
        { }

        /// <summary>
        /// 开启计时
        /// </summary>
        protected internal void StartTiming()
        {
            _StartTime = DateTime.Now;
        }
        /// <summary>
        /// 开始计时时间，如果异步操作DBContext会出现计时执行时间不正确
        /// </summary>
        DateTime _StartTime;
        /// <summary>
        /// 停止计时并返回所计时秒数（含小数）
        /// </summary>
        protected internal void SetTiming<TEntity>(EmDbContextMethod contextMethod, BaseResult result)
            where TEntity : class, new()
        {
            var tbName = EntityAnaly.GetTableName<TEntity>();
            result.TableName = tbName;
            SetTiming(contextMethod, result);
        }

        protected internal void SetTiming(EmDbContextMethod contextMethod, BaseResult result)
        {
            result.ResultMark = contextMethod.ToString();
            result.SetTiming(_StartTime, ResultFinish);
        }

        protected virtual void ResultFinish(BaseResult result)
        { }

        public new ExecResult ExecSql(ISqlBuilder sqlBuilder)
        {
            StartTiming();
            var r = base.ExecSql(sqlBuilder);
            SetTiming(EmDbContextMethod.ExecSql, r);
            return r;
        }
        //public virtual ExecResult ExecSql(ISqlBuilder sqlBuilder)
        //{
        //    StartTiming();
        //    var r = base.ExecSql(sqlBuilder);
        //    SetTiming(EmDbContextMethod.ExecSql, r);
        //    return r;
        //}

        public override int InsertBulk<TEntity>(List<TEntity> dataList)
        {
            StartTiming();
            var rowCount = base.InsertBulk(dataList);
            ExecResult r = new ExecResult(rowCount, null);
            SetTiming<TEntity>(EmDbContextMethod.InsertBulk, r);
            return rowCount;
        }

        public override ExecResult Insert<TEntity>(TEntity entity)
        {
            StartTiming();
            var r = base.Insert(entity);
            SetTiming<TEntity>(EmDbContextMethod.Insert, r);
            return r;
        }

        public override ExecResult Update<TEntity>(TEntity entity)
        {
            StartTiming();
            var r = base.Update(entity);
            SetTiming<TEntity>(EmDbContextMethod.Update, r);
            return r;
        }

        public override ExecResult Update<TEntity>(TEntity entity, ICondition condition)
        {
            StartTiming();
            var r = base.Update(entity, condition);
            SetTiming<TEntity>(EmDbContextMethod.UpdateCondition, r);
            return r;
        }

        public override ExecResult Update<TEntity>(TEntity entity, Expression<Func<TEntity, bool>> lamda)
        {
            StartTiming();
            var r = base.Update(entity, lamda);
            SetTiming<TEntity>(EmDbContextMethod.UpdateLamda, r);
            return r;
        }

        public override ExecResult Delete<TEntity>(Expression<Func<TEntity, bool>> lamda)
        {
            StartTiming();
            var r = base.Delete(lamda);
            SetTiming<TEntity>(EmDbContextMethod.DeleteLamda, r);
            return r;
        }

        public override ExecResult Delete<TEntity>(ICondition condition)
        {
            StartTiming();
            var r = base.Delete<TEntity>(condition);
            SetTiming<TEntity>(EmDbContextMethod.DeleteCondition, r);
            return r;
        }

        public override ExecResult Delete<TEntity>(TEntity entity)
        {
            StartTiming();
            var r = base.Delete(entity);
            SetTiming<TEntity>(EmDbContextMethod.Delete, r);
            return r;
        }

        public override QueryResult Query(ISqlBuilder sqlBuilder)
        {
            StartTiming();
            var r = base.Query(sqlBuilder);
            SetTiming(EmDbContextMethod.QuerySql, r);
            return r;
        }

        public override QueryResult<TRet> Query<TTable, TRet>(QueryCondition<TTable> condition, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.Query<TTable, TRet>(condition, joinWhereBuilder);
            SetTiming<TTable>(EmDbContextMethod.QueryLamda, r);
            return r;
        }

        //public override QueryResult<TEntity> Query<TEntity>(Expression<Func<TEntity, bool>> lamda)
        //{
        //    StartTiming();
        //    var r = base.Query(lamda);
        //    SetTiming<TEntity>(EmDbContextMethod.QueryLamda, r);
        //    return r;
        //}

        //public override QueryResult<TEntity> Query<TEntity>(ISqlBuilder whereSqlBuilder)
        //{
        //    StartTiming();
        //    var r = base.Query<TEntity>(whereSqlBuilder);
        //    SetTiming<TEntity>(EmDbContextMethod.QueryWhereSql, r);
        //    return r;
        //}

        //public override QueryResult<TEntity> Query<TEntity>(IQueryCondition condition)
        //{
        //    StartTiming();
        //    var r = base.Query<TEntity>(condition);
        //    SetTiming<TEntity>(EmDbContextMethod.QueryCondition, r);
        //    return r;
        //}

        //public override QueryResult<TEntity> Query<TEntity>(IQueryCondition condition, ISqlBuilder joinWhereBuilder)
        //{
        //    StartTiming();
        //    var r = base.Query<TEntity>(condition, joinWhereBuilder);
        //    SetTiming<TEntity>(EmDbContextMethod.QueryConditionAndSql, r);
        //    return r;
        //}

        public override ScalarResult QueryCountResult<TEntity>(IQueryCondition condition, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryCountResult<TEntity>(condition, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryCountCondition, r);
            return r;
        }

        public override ScalarResult QueryCountResult<TEntity>(Expression<Func<TEntity, bool>> lamda, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryCountResult<TEntity>(lamda, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryCountLamda, r);
            return r;
        }

        public override ScalarResult QueryMax<TEntity>(Expression<Func<TEntity, object>> selector, Expression<Func<TEntity, bool>> lamda, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryMax(selector, lamda, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryMinLamda, r);
            return r;
        }

        public override ScalarResult QueryMax<TEntity>(Expression<Func<TEntity, object>> selector, IQueryCondition condition, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryMax(selector, condition, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryMaxCondition, r);
            return r;
        }

        public override ScalarResult QueryMin<TEntity>(Expression<Func<TEntity, object>> selector, Expression<Func<TEntity, bool>> lamda, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryMin(selector, lamda, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryMinLamda, r);
            return r;
        }

        public override ScalarResult QueryMin<TEntity>(Expression<Func<TEntity, object>> selector, IQueryCondition condition, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QueryMin(selector, condition, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QueryMinCondition, r);
            return r;
        }

        public override ScalarResult QueryScalar(ISqlBuilder sqlBuilder)
        {
            StartTiming();
            var r = base.QueryScalar(sqlBuilder);
            SetTiming(EmDbContextMethod.QueryScalarSql, r);
            return r;
        }

        public override ScalarResult QuerySum<TEntity>(Expression<Func<TEntity, object>> selector, Expression<Func<TEntity, bool>> lamda, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QuerySum(selector, lamda, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QuerySumLamda, r);
            return r;
        }

        public override ScalarResult QuerySum<TEntity>(Expression<Func<TEntity, object>> selector, IQueryCondition condition, ISqlBuilder joinWhereBuilder = null)
        {
            StartTiming();
            var r = base.QuerySum(selector, condition, joinWhereBuilder);
            SetTiming<TEntity>(EmDbContextMethod.QuerySumCondition, r);
            return r;
        }

        public override ProcResult ExecProcedure<ProcEntity>(ProcEntity procObj, Dictionary<string, object> otherArgs)
        {
            StartTiming();
            var r = base.ExecProcedure(procObj, otherArgs);
            r.TableName = procObj.GetProcedureName();
            SetTiming(EmDbContextMethod.ExecProcedure, r);
            return r;
        }
    }
}